package com.airport.schedule;

import com.airport.schedule.model.AdHocRule;
import com.airport.schedule.model.Flight;
import com.airport.schedule.model.FlightGate;
import com.airport.schedule.util.FileUtil;
import com.airport.schedule.util.ListUtil;
import com.airport.schedule.util.Pair;
import com.airport.schedule.util.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import java.io.IOException;
import java.util.*;


public class ProblemLoader {

    private static final List<Flight> flights = new ArrayList<>();
    private static final List<FlightGate> flightGates = new ArrayList<>();

    public static List<Flight> getFlights() {
        return flights;
    }

    public static List<FlightGate> getFlightGates() {
        return flightGates;
    }

    private static boolean hasLoad = false;

    public static void loads(String filename, int limit) {
        if(hasLoad) return;
        hasLoad = true;
        try {
            Workbook wb = FileUtil.readWorkbook(filename);
            Sheet histories = wb.getSheet("历史航班");
            Sheet constraints = wb.getSheet("机位属性表");
            for(int index = 1; index <= histories.getLastRowNum() && index <= limit; index++) {
                Row row = histories.getRow(index);
                flights.add(new Flight(
                        getStringValue(row.getCell(0)),
                        getStringValue(row.getCell(1)),
                        getStringValue(row.getCell(2)),
                        getStringValue(row.getCell(3)),
                        getStringValue(row.getCell(4)),
                        getStringValue(row.getCell(5)),
                        getStringValue(row.getCell(6)),
                        getStringValue(row.getCell(7))
                ));
            }

            for(int index = 1; index <= constraints.getLastRowNum(); index++) {
                Row row = constraints.getRow(index);
                String gateId = getStringValue(row.getCell(1));
                if(gateId.endsWith("ZJ") || gateId.endsWith("YJ")) {
                    String[] ids = gateId.split("/");
                    for(String id : ids) {
                        Set<String> homogenyGates = new HashSet<>();
                        int curId = Integer.valueOf(id.substring(0,id.length()-2));
                        if(id.endsWith("ZJ")) {
                            int lastId = curId-1;
                            if(lastId >= 501) {
                                homogenyGates.add(lastId+"L");
                            }
                            if(curId != 501) {
                                homogenyGates.add(curId+"YJ");
                            }
                            homogenyGates.add(curId+"");
                        }else{
                            if(curId != 515) {
                                homogenyGates.add(curId+"L");
                                homogenyGates.add(curId+"ZJ");
                            }
                            homogenyGates.add(curId+"");
                        }
                        AdHocRule rule = new AdHocRule(new HashSet<>(),new HashSet<>(), homogenyGates, AdHocRule.IS_DOWN_GREDE);
                        flightGates.add(new FlightGate(
                                id,
                                getStringValue(row.getCell(2)),
                                getStringValue(row.getCell(3)),
                                getStringValue(row.getCell(4)),
                                getStringValue(row.getCell(5)),
                                getStringValue(row.getCell(6)),
                                getStringValue(row.getCell(7)),
                                getStringValue(row.getCell(8)),
                                rule
                        ));
                    }
                    continue;
                }
                AdHocRule rule = null;
                if(gateId.endsWith("A")) { // 父子机位
                    int id = Integer.valueOf(gateId.substring(0,gateId.length()-1));
                    String constraint = getStringValue(row.getCell(9));
                    Pair<Integer,Integer> fromTo = StringUtils.extractFromTo(constraint);
                    Set<String> obstructGates = new HashSet<>();
                    for(int i = fromTo.head; i <= fromTo.tail; i++) {
                        obstructGates.add(i+"");
                    }
                    Set<String> homogenyGates = new HashSet<>();
                    homogenyGates.add(id + "");
                    if(id == 419) {
                        homogenyGates.add(id - 1 + "");
                    }else{
                        homogenyGates.add(id + 1 + "");
                    }
                    if(id == 413) {
                        obstructGates.add("416A");
                        obstructGates.add("419A");
                    }
                    if(id == 416) {
                        obstructGates.add("419A");
                    }
                    rule = new AdHocRule(obstructGates, new HashSet<>(), homogenyGates, AdHocRule.IS_COMPOSITE);
                }else if(gateId.startsWith("L")) { // 临时机位
                    String constraint = getStringValue(row.getCell(9));
                    Set<String> obstructs = new HashSet<>(ListUtil.map(Arrays.asList(constraint.split(","))
                            , String::trim));
                    if(gateId.equals("L515")) {
                        obstructs.addAll(Arrays.asList("513ZJ","513YJ","514ZJ","514YJ","515YJ"));
                    }
                    rule = new AdHocRule(new HashSet<>(), obstructs, new HashSet<>(), AdHocRule.IS_RUNWAY_GATE);
                }else if(gateId.endsWith("L")) { // 减容产生的机位
                    int id = Integer.valueOf(gateId.substring(0,gateId.length()-1));
                    Set<String> homogenyGates = new HashSet<>();
                    int nextGate = id+1;
                    if(id != 501) {
                        homogenyGates.add(id+"YJ");
                    }
                    homogenyGates.add(""+id);
                    if(nextGate < 515) {
                        homogenyGates.add(nextGate+"ZJ");
                    }
                    if(nextGate <= 515) {
                        homogenyGates.add(nextGate+"");
                    }
                    rule = new AdHocRule(new HashSet<>(), new HashSet<>(), homogenyGates, AdHocRule.IS_DOWN_GREDE);
                }
                flightGates.add(new FlightGate(
                        getStringValue(row.getCell(1)),
                        getStringValue(row.getCell(2)),
                        getStringValue(row.getCell(3)),
                        getStringValue(row.getCell(4)),
                        getStringValue(row.getCell(5)),
                        getStringValue(row.getCell(6)),
                        getStringValue(row.getCell(7)),
                        getStringValue(row.getCell(8)),
                        rule
                ));
            }
            System.out.println("问题载入成功！总航班数量="+flights.size()+" 机位数量="+flightGates.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String getStringValue(Cell cell) {
        if(cell == null) return "";
        int type = cell.getCellType();
        switch (type) {
            case Cell.CELL_TYPE_STRING:
                return cell.getStringCellValue().trim();
            case Cell.CELL_TYPE_NUMERIC:
                if(HSSFDateUtil.isCellDateFormatted(cell)) {
                    return HSSFDateUtil.getJavaDate(cell.getNumericCellValue()).getTime()+"";
                }
                return String.valueOf((int)cell.getNumericCellValue());
            case Cell.CELL_TYPE_BLANK:
                return "";
        }
        return "";
    }

    public static void descGates() {
        flightGates.forEach(g->{
            if(g.isAdHocGate()) {
                System.out.println(g.getFlightGateId()+" "+g.getRule());
            }
        });
    }

    public static void showNoFlightGate(boolean useAdhocFlightGate) {
        for(Flight flight : flights) {
            boolean hasGate = false;
            for(FlightGate gate : flightGates) {
                if(gate.isAdHocGate()) {
                    if(useAdhocFlightGate && gate.acceptFlight(flight)) {
                        hasGate = true;
                        break;
                    }
                }else{
                    if(gate.acceptFlight(flight)) {
                        hasGate = true;
                        break;
                    }
                }
            }
            if(!hasGate) {
                System.out.println(flight.getFlightId());
            }
        }
    }

    public static void main(String args[]) {
        String os = System.getProperty("os.name");
        String dir = "/Users/carlxie/Downloads/";
        if(os.toLowerCase().startsWith("win")){
            dir = "D:/";
        }
        ProblemLoader.loads(dir+"airportdata/data.xlsx", 10000);
        ProblemLoader.descGates();
//        ProblemLoader.showNoFlightGate(true);
    }

}
